package com.easylinkin.linkappapi.powerdistribution.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.linkappapi.common.exceptions.BusinessException;
import com.easylinkin.linkappapi.common.service.CommonService;
import com.easylinkin.linkappapi.common.utils.io.OutputStreamUtil;
import com.easylinkin.linkappapi.powerdistribution.entity.DistributionCabinetType;
import com.easylinkin.linkappapi.powerdistribution.entity.DistributionCabinetTypeSite;
import com.easylinkin.linkappapi.powerdistribution.mapper.DistributionCabinetTypeMapper;
import com.easylinkin.linkappapi.powerdistribution.service.DistributionCabinetConfigurationService;
import com.easylinkin.linkappapi.powerdistribution.service.DistributionCabinetTypeService;
import com.easylinkin.linkappapi.powerdistribution.service.DistributionCabinetTypeSiteService;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import com.easylinkin.linkappapi.security.entity.LinkappUser;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

/**
 * <p>
 * 配电柜类型 服务实现类
 * </p>
 *
 * @author TongJie
 * @since 2020-08-05
 */
@Service
public class DistributionCabinetTypeServiceImpl extends ServiceImpl<DistributionCabinetTypeMapper, DistributionCabinetType> implements DistributionCabinetTypeService {


    private static final Logger LOGGER = LoggerFactory.getLogger(DistributionCabinetTypeServiceImpl.class);

    @Resource
    private CommonService commonService;
    @Resource
    private LinkappUserContextProducer linkappUserContextProducer;
    @Resource
    private DistributionCabinetTypeSiteService distributionCabinetTypeSiteService;
    @Resource
    private DistributionCabinetConfigurationService distributionCabinetConfigurationService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(DistributionCabinetType distributionCabinetType) {
        validParamRequired(distributionCabinetType);
        validParamFormat(distributionCabinetType);
        validRepeat(distributionCabinetType);
        commonService.setCreateAndModifyInfo(distributionCabinetType);
        LinkappUser user = linkappUserContextProducer.getCurrent();
        distributionCabinetType.setTenantId(user.getTenantId());
        save(distributionCabinetType);
        List<DistributionCabinetTypeSite> distributionCabinetTypeSiteList = distributionCabinetType.getDistributionCabinetTypeSiteList();
        Assert.notEmpty(distributionCabinetTypeSiteList, "distributionCabinetTypeSiteList 为空");
        distributionCabinetTypeSiteList.forEach(distributionCabinetTypeSite -> {
            distributionCabinetTypeSite.setDistributionCabinetTypeId(distributionCabinetType.getId());
            distributionCabinetTypeSiteService.add(distributionCabinetTypeSite);
        });
    }


    /**
     * 校验重复
     */
    private void validRepeat(DistributionCabinetType distributionCabinetType) {
        QueryWrapper<DistributionCabinetType> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name", distributionCabinetType.getName());
        queryWrapper.eq("tenant_id", linkappUserContextProducer.getNotNullCurrent().getTenantId());

        List<DistributionCabinetType> list = baseMapper.selectList(queryWrapper);
        if (list.size() == 0) {
            return;
        }
        if (list.size() > 1) {
            throw new BusinessException("配电柜类型名称有重复");
        }
        if (StringUtils.isEmpty(distributionCabinetType.getId())) {
            throw new BusinessException("配电柜类型名称已存在");
        }
        if (!distributionCabinetType.getId().equals(list.get(0).getId())) {
            throw new BusinessException("配电柜类型名称已存在");
        }
        
    }


    /**
     * 校验参数必填
     */
    private void validParamRequired(DistributionCabinetType distributionCabinetType) {
        Assert.notNull(distributionCabinetType, "参数为空");
        Assert.isTrue(StringUtils.isNotBlank(distributionCabinetType.getName()), "名称为空");


    }

    /**
     * 校验参数格式
     */
    private void validParamFormat(DistributionCabinetType distributionCabinetType) {
        Assert.isTrue(distributionCabinetType.getName() == null || distributionCabinetType.getName().length() <= 32, "名称超长");
        Assert.isTrue(distributionCabinetType.getDescription() == null || distributionCabinetType.getDescription().length() <= 255, "配电柜类型描述超长");
        Assert.isTrue(distributionCabinetType.getTenantId() == null || distributionCabinetType.getTenantId().length() <= 32, "租户id超长");
    }

    @Override
    public List<DistributionCabinetType> getDistributionCabinetTypes(DistributionCabinetType distributionCabinetType) {
        distributionCabinetType.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        return baseMapper.getDistributionCabinetTypes(distributionCabinetType);
    }

    @Override
    public IPage<DistributionCabinetType> getDistributionCabinetTypes(Page page, DistributionCabinetType distributionCabinetType) {
        distributionCabinetType.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        return baseMapper.getDistributionCabinetTypes(page, distributionCabinetType);
    }

    @Override
    public DistributionCabinetType getDistributionCabinetType(String id) {
        return baseMapper.getDistributionCabinetType(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateDistributionCabinetType(DistributionCabinetType distributionCabinetType) {
        Assert.notNull(distributionCabinetType, "参数为空");
        DistributionCabinetType originDistributionCabinetType = getById(distributionCabinetType.getId());
        Assert.notNull(originDistributionCabinetType, "原配电柜类型不存在");
        validRepeat(distributionCabinetType);
        validParamFormat(distributionCabinetType);
        commonService.setModifyInfo(distributionCabinetType);
        updateById(distributionCabinetType);

//        删除之前的关联的位置
        QueryWrapper<DistributionCabinetTypeSite> qw = new QueryWrapper<>();
        qw.eq("distribution_cabinet_type_id", distributionCabinetType.getId());
        distributionCabinetTypeSiteService.remove(qw);

        //        新增关联的位置
        List<DistributionCabinetTypeSite> distributionCabinetTypeSiteList = distributionCabinetType.getDistributionCabinetTypeSiteList();
        Assert.notEmpty(distributionCabinetTypeSiteList, "distributionCabinetTypeSiteList 为空");
        distributionCabinetTypeSiteList.forEach(distributionCabinetTypeSite -> {
            distributionCabinetTypeSite.setDistributionCabinetTypeId(distributionCabinetType.getId());
            distributionCabinetTypeSiteService.add(distributionCabinetTypeSite);
        });

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteBatch(List<DistributionCabinetType> distributionCabinetTypeList) {
        Assert.notEmpty(distributionCabinetTypeList, "参数为空");
        List<String> ids = distributionCabinetTypeList.stream().map(DistributionCabinetType::getId).collect(Collectors.toList());

        QueryWrapper qw = new QueryWrapper();
        qw.select("id");
        qw.in("distribution_cabinet_type_id", ids);
        List<DistributionCabinetTypeSite> distributionCabinetTypeSiteList = distributionCabinetTypeSiteService.list(qw);
        List<String> siteIds = distributionCabinetTypeSiteList.stream().map(DistributionCabinetTypeSite::getId).collect(Collectors.toList());
        if (ObjectUtils.isNotEmpty(siteIds)) {
            qw = new QueryWrapper();
            qw.in("distribution_cabinet_type_site_id", siteIds);
//        删除对应组态
            distributionCabinetConfigurationService.remove(qw);
//        删除相关的位置信息
            distributionCabinetTypeSiteService.removeByIds(siteIds);
        }
        removeByIds(ids);
    }


    @Override
    public void exportData(DistributionCabinetType distributionCabinetType, HttpServletRequest request, HttpServletResponse response) {
        Assert.notNull(distributionCabinetType, "参数为空");
        Assert.notEmpty(distributionCabinetType.getIds(), "没有勾选任何数据，id为空");

        distributionCabinetType.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        List<DistributionCabinetType> distributionCabinetTypeList = baseMapper.getDistributionCabinetTypeAndCabinetTypeAndCabinetConfigurations(distributionCabinetType);
        Assert.notEmpty(distributionCabinetTypeList,"根据条件查得需要导出的数据为空");
        OutputStream outputStream = null;
        Writer write = null;
        try {
            outputStream = OutputStreamUtil
                .getOutputStream(request, response, "配电柜类型导出数据.json");
            write = new OutputStreamWriter(outputStream, "UTF-8");
        } catch (IOException e) {
            e.printStackTrace();
            LOGGER.error("配电柜导出过程生成输出流异常",e);
            return;
        }

        try {
            write.write(JSON.toJSONString(distributionCabinetTypeList));
            write.flush();
            response.flushBuffer();
        } catch (IOException e) {
            LOGGER.error("excel导出失败",e);
            throw new RuntimeException("excel导出失败！IOException异常" + e.getMessage());
        } catch (Exception e) {
            LOGGER.error("excel导出失败", e);
            throw new RuntimeException("excel导出失败！" + e.getMessage());
        } finally {
            try {
                outputStream.close();
                write.close();
            } catch (IOException e) {
                e.printStackTrace();
                LOGGER.error("配电柜导出过程,输出流关闭异常",e);
            }
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Set importData(MultipartFile file) {
        Set deviceErrorList = new HashSet();
        BufferedReader bf = null;
        try {
            bf = new BufferedReader(new InputStreamReader(file.getInputStream()));
        } catch (IOException e) {
            e.printStackTrace();
            LOGGER.error("生成输入流错误！",e);
            return deviceErrorList;
        }
        String content = "";
        StringBuilder sb = new StringBuilder();
        try {
            while (content != null) {
                content = bf.readLine();
                if (content == null) {
                    break;
                }
                sb.append(content.trim());
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                bf.close();
            } catch (IOException e) {
                e.printStackTrace();
                LOGGER.info("关闭流失败！");
            }
        }
        List<DistributionCabinetType> distributionCabinetTypeList = JSON.parseArray(sb.toString(), DistributionCabinetType.class);
        for (DistributionCabinetType distributionCabinetType : distributionCabinetTypeList) {
            add(distributionCabinetType);
        }
        return deviceErrorList;
    }

}
